Examples used here:
Eugen is a Design System documentation tool based on CSS comments.
Writing a Design System is a complicated task and documenting it is tedious. As a big fan of Living Documentation, I have decided to develop this tiny tool to make the process easier.
Fun fact, this site is entirely built using eugen itself, check it yourself!
That's damn simple. Just add comments on top of your declarations with a @tagname
,
for example in my_styles.css
:
/** * @block: Represents a button * / .button { } /** * @block * Represents the sidebar * * @added_in: 1.2.0 * / .sidebar { }
Tag names can be anything that makes sense to you and not in the list of reserved
tags: declarations
, properties
, url
.
Create a template file for the @block
tag called templates/block.html
with the content:
<!-- Here you must use valid html but for this sample, no html, no head just body. Here, the title will be the element CSS declarations joined by a colon. --> <h1>{{ page.declarations | join(', ') }}</h1> <!-- Next, the content of the `@block` tag will be rendered using the markdown builtin filter. --> {{ page.block | markdown }} <!-- page properties are extracted from existing tags and are represented as a list of lines hence the `first` filter here to retrieve the value `1.2.0` for the sidebar example. --> {% if page.added_in %} <small>Component added in version {{ page.added_in | first }}</small> {% endif %}
eugen will group pages based on their tags and will try to render templates
matching those tags (here block
). By the way, the :root
element will be your index page
so it will be rendered with the index.html
template file if present.
And finally, launch the eugen CLI:
$ eugen my_styles.css -t templates -o _build -v
And voilĂ , your documentation is ready!
Writing templates is just as easy as the syntax itself and use Jinja2 as its template engine.
Create a directory containing your template files (in html or pugjs like syntax) and eugen will use them to render your site.
Here is the list of available variables inside a template:
page
: Current element being rendered (See Page data below)site
: Generated site objectcurrent_url
: Current url being generatedfrom_css_path
: A list of string containing the final path of CSS files from which the documentation is being generated. Use it to include them in your documentationIn order to make writing template easier, a bunch of filters has been included:
spenx(source)
: Convert a string to HTML using the spenx libraryjoin(lines, separator='')
: Join an array of strings using the given separatorfirst(value, default='')
: Returns the first element of an iterable or the default valuemarkdown(source)
: Convert a string or an array of strings to HTML using the markdown libraryprettify(value, formatter='html.parser')
: Prettify some HTML using BeautifulSoupunslugify(value)
: Try to convert a slug to a more friendlier stringhighlight(code, lexername=None)
: Highlight some code with the given lexer (ie. language). You can omit it and it will try to guess from the source code but it may cause performance issuesurl(path)
: Makes a relative url from a string, you should always use it in your templatesasset(path)
: Mark a path as an asset which means it will be copied to the output directory and a relative url will be usedPage data represents what eugen has parsed from your source CSS files. It's a dictionary with the following structure:
page = { '_': ['Contains every comments not tied to any eugen tag', 'and may span multiple lines'], 'url': lambda group='': 'lambda which returns the url relative to a group', 'declarations': ['.text', 'p', '.and-every-other-declaration], 'properties': [ { '_': ['Structure is the same as for the page data', 'except the name property.', 'properties here refers to CSS Custom Properties'], 'name': 'name-of-the-property', }, ], 'block': ['Contains all lines for the @block tag', 'here is another example with a @version tag'], 'version': ['1.0.0'], }